﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Core.Utility.Security
{
    /// <summary>
    /// Api签名
    /// </summary>
    public class ApiSignature
    {
        /// <summary>
        /// 
        /// </summary>
        public string? Token { get; private set; }
        
        /// <summary>
        /// 
        /// </summary>
        public long? Timeout { get; private set; }

        /// <summary>
        /// Api签名
        /// </summary>
        /// <param name="token"></param>
        /// <param name="timeout">超时时间，单位：秒，用于签名验证使用</param>
        public ApiSignature(string? token,long? timeout = 30)
        {
            Token = token;
            Timeout = timeout;
        }

        /// <summary>
        /// 生成签名
        /// <para>1.通过header获取传递的timestamp（时间戳）、nonce（随机字符串，十分钟内不允许重复）、data_signature（数据验签字符串/消息体签名，用于验证消息体的正确性）、signature（签名字符串）；</para>
        /// <para>2.获取本地的token，将token、timestamp（时间戳）、nonce（随机字符串，十分钟内不允许重复）、data_signature（数据验签字符串/消息体签名，用于验证消息体的正确性） 四个参数进行字典序排序；</para>
        /// <para>3.将token、timestamp（时间戳）、nonce（随机字符串，十分钟内不允许重复）、data_signature（数据验签字符串/消息体签名，用于验证消息体的正确性） </para>四个参数字符串拼接成一个字符串进行sha1加密（加密结果全小写）得到signature（签名字符串）；
        /// </summary>
        /// <param name="data">生成签名额外附加的数据</param>
        /// <returns>每次加密、签名产生的 timeStamp、nonce 不一样，注意存储及传参</returns>
        public ReturnResultInfo<ApiSignatureInfo> Create(string? data = "")
        {
            ReturnResultInfo<ApiSignatureInfo> res;// = new ReturnResultInfo<ApiSignatureData>(message:"签名失败");
            ApiSignatureInfo apiData = new ApiSignatureInfo();
            var genarateRes = ApiSecurity.Signature(Token, apiData.TimeStamp?.ToString(), apiData.Nonce, data);
            res = ReturnResultInfo.Convert<ApiSignatureInfo, string>(genarateRes, apiData);
            if (genarateRes.Successed)
            {
                if (res.Data != null)
                {
                    res.Data.SetSignature(genarateRes.Data);
                }
            }
            return res;
        }


        /// <summary>
        /// 验签，验签原理：传入签名涉及的参数，进行签名，将签名后的结果与传入的签名进行全等判断，一致返回true，否则返回false
        /// </summary>
        /// <param name="hashSignature">验证签名字符串</param>
        /// <param name="timeStamp">时间戳</param>
        /// <param name="nonce">随机字符串</param>
        /// <param name="data">生成签名额外附加的数据</param>
        /// <returns></returns>
        public ReturnResultInfo Verify(string? hashSignature, long? timeStamp, string? nonce, string? data = "")
        {
            var verifyRes = ApiSecurity.VerifySignature(hashSignature, Token, timeStamp?.ToString(), nonce, data, Timeout);
            return verifyRes;
        }

        /// <summary>
        /// 验签，验签原理：传入签名涉及的参数，进行签名，将签名后的结果与传入的签名进行全等判断，一致返回true，否则返回false
        /// </summary>
        /// <param name="hashSignature">验证签名字符串</param>
        /// <param name="timeStamp">时间戳</param>
        /// <param name="nonce">随机字符串</param>
        /// <param name="data">生成签名额外附加的数据</param>
        /// <param name="timeout">为null或&lt;0不验证超时</param>
        /// <returns></returns>
        public ReturnResultInfo Verify(string? hashSignature,long? timeStamp, string? nonce, long? timeout, string? data = "")
        {
            var verifyRes = ApiSecurity.VerifySignature(hashSignature, Token, timeStamp?.ToString(), nonce, data, timeout);
            return verifyRes;
        }

        /// <summary>
        /// 设置Token
        /// </summary>
        /// <param name="value"></param>
        public void SetToken(string? value)
        {
            Token = value;
        }

        /// <summary>
        /// 设置超时时间
        /// </summary>
        /// <param name="value"></param>
        public void SetTimeOut(long value)
        {
            Timeout = value;
        }
    }
}
